`include "defines.v"
module id(
	input wire rst,
	input wire[31:0] pc_i,
	input wire[31:0] inst_i,
	input wire[31:0] reg1_data_i,
	input wire[31:0] reg2_data_i,
	output reg[4:0] reg1_addr_o,
	output reg[4:0] reg2_addr_o,
	output reg reg1_read_o,
	output reg reg2_read_o,
	//传给id_ex模块的信号
	output reg[31:0] reg1_o,
	output reg[31:0] reg2_o,
	output reg[4:0] reg3_addr_o,
	output reg reg3_write_o,
	output reg[`AluOpWidth-1:0] alu_op_o,
	// output reg[`AluSelWidth-1:0] alu_sel_o
	
	//执行模块传给译码模块的信号（解决数据相关）
	input wire[4:0] ex_write_addr_i,
	input wire ex_write_ce_i,
	input wire[31:0] ex_write_data_i,
	//访存模块传给译码模块的信号（解决数据相关）
	input wire[4:0] mem_write_addr_i,
	input wire mem_write_ce_i,
	input wire[31:0] mem_write_data_i,
	//控制流水线暂停信号
	output wire pause_o,
	//转移分支指令相关信号
	output reg[31:0] jAddr_o,
	output reg jCe_o,
	output reg next_inst_is_in_delaySlot_o, //下一条进入译码阶段的指令是否是延迟槽指令
	output reg[31:0] link_addr_o, //返回地址
	output reg is_in_delaySlot_o, //当前译码阶段的指令是否是延迟槽指令
	input wire is_in_delaySlot_i, //当前译码阶段的指令是否是延迟槽指令
	output wire[31:0] inst_o,
	input wire[`AluOpWidth-1:0] ex_alu_op_i //当前执行阶段的aluop
);
	reg[31:0] imm;
	reg inst_valid;
	wire[31:0] pc_add_4 = pc_i + 4;
	wire[31:0] pc_add_8 = pc_i + 8;
	reg load_pause;
	assign pause_o = load_pause;
	
	assign inst_o = inst_i;
	//判断是否发生load相关，发生则暂停流水线
	always@(*)
		if(rst == `RstEnable)
			load_pause = `NO_PAUSE;
		else if(ex_alu_op_i == `ALU_LB_OP ||
				ex_alu_op_i == `ALU_LBU_OP ||
				ex_alu_op_i == `ALU_LH_OP ||
				ex_alu_op_i == `ALU_LHU_OP ||
				ex_alu_op_i == `ALU_LL_OP ||
				ex_alu_op_i == `ALU_LW_OP ||
				ex_alu_op_i == `ALU_LWL_OP ||
				ex_alu_op_i == `ALU_LWR_OP ||
				ex_alu_op_i == `ALU_SC_OP)
			begin
				if(reg1_read_o == `ReadEnable &&
					reg1_addr_o == ex_write_addr_i &&
					ex_write_ce_i == `WriteEnable
				)
					load_pause = `PAUSE;
				if(reg2_read_o == `ReadEnable &&
					reg2_addr_o == ex_write_addr_i &&
					ex_write_ce_i == `WriteEnable
				)
					load_pause = `PAUSE;
					
			end
		else
			load_pause = `NO_PAUSE;
			
	//主要译码逻辑
	always@(*)
		if(rst == `RstEnable) 
		begin
			reg1_addr_o = 5'b00000;
			reg2_addr_o = 5'b00000;
			reg1_read_o = `ReadDisable;
			reg2_read_o = `ReadDisable;
			reg3_addr_o = 5'b0;
			reg3_write_o = `WriteDisable;
			alu_op_o =  `ALU_NOP_OP;
			// alu_sel_o = `ALU_RES_NOP;
			imm = `ZeroWord;
			inst_valid = `InstInvalid;
			jAddr_o = `ZeroWord;
			jCe_o = `JumpDisable;
			next_inst_is_in_delaySlot_o = `NotInDelaySlot;
			link_addr_o = `ZeroWord;
		end
		else 
		begin
			// reg1_addr_o = inst_i[25:21]; //reg1_addr_o默认代表rs地址
			// reg2_addr_o = inst_i[20:16]; //reg2_addr_o默认代表rt地址
			// reg1_read_o = `ReadDisable; //默认读无效
			// reg2_read_o = `ReadDisable; //默认读无效
			// reg3_addr_o = inst_i[15:11]; //reg3_addr_o默认代表rd地址
			// reg3_write_o = `WriteDisable; //默认写无效
			// alu_op_o =  `ALU_NOP_OP; //默认ALU空操作
			// alu_sel_o = `ALU_RES_NOP; //默认空类型运算
			// imm = `ZeroWord; //默认立即数为0
			// inst_valid = `InstInvalid; //默认指令无效
			reg1_addr_o = 5'b00000; 
			reg2_addr_o = 5'b00000; 
			reg1_read_o = `ReadDisable; 
			reg2_read_o = `ReadDisable;
			reg3_addr_o = 5'b00000; 
			reg3_write_o = `WriteDisable;
			alu_op_o =  `ALU_NOP_OP; 
			// alu_sel_o = `ALU_RES_NOP; 
			imm = `ZeroWord; 
			inst_valid = `InstInvalid;
			//分支相关
			jAddr_o = `ZeroWord;
			jCe_o = `JumpDisable;
			next_inst_is_in_delaySlot_o = `NotInDelaySlot;
			link_addr_o = `ZeroWord;
			case(inst_i[31:26])
				`INST_ORI:
				begin
					reg1_addr_o = inst_i[25:21]; 
					reg2_addr_o = 5'b00000; 
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16];
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_OR_OP; 
					// alu_sel_o = `ALU_RES_LOGIC; 
					imm = {16'b0, inst_i[15:0]};
					inst_valid = `InstValid;
				end
				`INST_ANDI:
				begin
					reg1_addr_o = inst_i[25:21]; 
					reg2_addr_o = 5'b00000; 
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16];
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_AND_OP; 
					imm = {16'b0, inst_i[15:0]};
					inst_valid = `InstValid;
				end
				`INST_XORI:
				begin
					reg1_addr_o = inst_i[25:21]; 
					reg2_addr_o = 5'b00000; 
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16];
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_XOR_OP; 
					imm = {16'b0, inst_i[15:0]};
					inst_valid = `InstValid;
				end
				`INST_LUI:
				begin
					reg1_addr_o = 5'b00000; 
					reg2_addr_o = 5'b00000; 
					reg1_read_o = `ReadDisable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16];
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_LUI_OP; 
					imm = {inst_i[15:0], 16'b0};
					inst_valid = `InstValid;
				end
				`INST_PREF:
				begin
					reg1_addr_o = 5'b00000; 
					reg2_addr_o = 5'b00000; 
					reg1_read_o = `ReadDisable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = 5'b00000; 
					reg3_write_o = `WriteDisable;
					alu_op_o =  `ALU_NOP_OP;
					imm = `ZeroWord; 
					inst_valid = `InstValid;
				end
				`INST_ADDI:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = 5'b00000;
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16]; 
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_ADD_OP;
					imm = {{16{inst_i[15]}}, inst_i[15:0]}; 
					inst_valid = `InstValid;
				end
				`INST_ADDIU:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = 5'b00000;
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16]; 
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_ADDU_OP;
					imm = {{16{inst_i[15]}}, inst_i[15:0]}; 
					inst_valid = `InstValid;
				end
				`INST_SLTI:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = 5'b00000;
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16]; 
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_SLT_OP;
					imm = {{16{inst_i[15]}}, inst_i[15:0]}; 
					inst_valid = `InstValid;
				end
				`INST_SLTIU:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = 5'b00000;
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16]; 
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_SLTU_OP;
					imm = {{16{inst_i[15]}}, inst_i[15:0]}; 
					inst_valid = `InstValid;
				end
				`INST_J:
				begin
					reg1_addr_o = 5'b00000; 
					reg2_addr_o = 5'b00000; 
					reg1_read_o = `ReadDisable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = 5'b00000; 
					reg3_write_o = `WriteDisable;
					alu_op_o =  `ALU_NOP_OP; 
					imm = `ZeroWord; 
					inst_valid = `InstValid;
					jAddr_o = {pc_add_4[31:28], inst_i[25:0], 2'b00};
					jCe_o = `JumpEnable;
					next_inst_is_in_delaySlot_o = `InDelaySlot;
				end
				`INST_JAL:
				begin
					reg1_addr_o = 5'b00000; 
					reg2_addr_o = 5'b00000; 
					reg1_read_o = `ReadDisable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = 5'b11111; 
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_LINK_OP; 
					imm = `ZeroWord; 
					inst_valid = `InstValid;
					jAddr_o = {pc_add_4[31:28], inst_i[25:0], 2'b00};
					jCe_o = `JumpEnable;
					next_inst_is_in_delaySlot_o = `InDelaySlot;
					link_addr_o = pc_add_8;
				end
				
				`INST_BEQ:
				begin
					reg1_addr_o = inst_i[25:21]; 
					reg2_addr_o = inst_i[20:16]; 
					reg1_read_o = `ReadEnable;
					reg2_read_o = `ReadEnable;
					reg3_addr_o = 5'b00000; 
					reg3_write_o = `WriteDisable;
					alu_op_o = `ALU_NOP_OP; 
					imm = {{14{inst_i[15]}}, inst_i[15:0], 2'b00};
					inst_valid = `InstValid;
					if(reg1_o == reg2_o)
					begin
						jAddr_o = pc_add_4 + imm;
						jCe_o = `JumpEnable;
						next_inst_is_in_delaySlot_o = `InDelaySlot;
					end
				end
				`INST_BNE:
				begin
					reg1_addr_o = inst_i[25:21]; 
					reg2_addr_o = inst_i[20:16]; 
					reg1_read_o = `ReadEnable;
					reg2_read_o = `ReadEnable;
					reg3_addr_o = 5'b00000; 
					reg3_write_o = `WriteDisable;
					alu_op_o =  `ALU_NOP_OP; 
					imm = {{14{inst_i[15]}}, inst_i[15:0], 2'b00};
					inst_valid = `InstValid;
					if(reg1_o != reg2_o)
					begin
						jAddr_o = pc_add_4 + imm;
						jCe_o = `JumpEnable;
						next_inst_is_in_delaySlot_o = `InDelaySlot;
					end	
				end
				`INST_BGTZ:
				begin
					reg1_addr_o = inst_i[25:21]; 
					reg2_addr_o = 5'b00000; 
					reg1_read_o = `ReadEnable;
					reg2_read_o = `ReadDisable;
					reg3_addr_o = 5'b00000; 
					reg3_write_o = `WriteDisable;
					alu_op_o =  `ALU_NOP_OP; 
					imm = {{14{inst_i[15]}}, inst_i[15:0], 2'b00};
					inst_valid = `InstValid;
					if((reg1_o[31] == 1'b0) && (reg1_o != `ZeroWord))
					begin
						jAddr_o = pc_add_4 + imm;
						jCe_o = `JumpEnable;
						next_inst_is_in_delaySlot_o = `InDelaySlot;
					end	
				end
				`INST_BLEZ:
				begin
					reg1_addr_o = inst_i[25:21]; 
					reg2_addr_o = 5'b00000; 
					reg1_read_o = `ReadEnable;
					reg2_read_o = `ReadDisable;
					reg3_addr_o = 5'b00000; 
					reg3_write_o = `WriteDisable;
					alu_op_o =  `ALU_NOP_OP; 
					imm = {{14{inst_i[15]}}, inst_i[15:0], 2'b00};
					inst_valid = `InstValid;
					if(reg1_o[31] == 1'b1 || reg1_o == `ZeroWord)
					begin
						jAddr_o = pc_add_4 + imm;
						jCe_o = `JumpEnable;
						next_inst_is_in_delaySlot_o = `InDelaySlot;
					end	
				end
				`INST_LB:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = 5'b00000;
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16]; 
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_LB_OP;
					imm = `ZeroWord; 
					inst_valid = `InstValid;
				end
				`INST_LBU:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = 5'b00000;
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16]; 
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_LBU_OP;
					imm = `ZeroWord; 
					inst_valid = `InstValid;
				end
				`INST_LH:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = 5'b00000;
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16]; 
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_LH_OP;
					imm = `ZeroWord; 
					inst_valid = `InstValid;
				end
				`INST_LHU:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = 5'b00000;
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16]; 
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_LHU_OP;
					imm = `ZeroWord; 
					inst_valid = `InstValid;
				end
				`INST_LW:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = 5'b00000;
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16]; 
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_LW_OP;
					imm = `ZeroWord; 
					inst_valid = `InstValid;
				end
				`INST_LWL:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = inst_i[20:16];
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadEnable;
					reg3_addr_o = inst_i[20:16]; 
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_LWL_OP;
					imm = `ZeroWord; 
					inst_valid = `InstValid;
				end
				`INST_LWR:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = inst_i[20:16];
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadEnable;
					reg3_addr_o = inst_i[20:16]; 
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_LWR_OP;
					imm = `ZeroWord; 
					inst_valid = `InstValid;
				end
				`INST_LL:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = 5'b00000;
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadDisable;
					reg3_addr_o = inst_i[20:16]; 
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_LL_OP;
					imm = `ZeroWord; 
					inst_valid = `InstValid;
				end
				`INST_SB:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = inst_i[20:16];
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadEnable;
					reg3_addr_o = 5'b00000; 
					reg3_write_o = `WriteDisable;
					alu_op_o =  `ALU_SB_OP;
					imm = `ZeroWord; 
					inst_valid = `InstValid;
				end
				`INST_SH:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = inst_i[20:16];
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadEnable;
					reg3_addr_o = 5'b00000; 
					reg3_write_o = `WriteDisable;
					alu_op_o =  `ALU_SH_OP;
					imm = `ZeroWord; 
					inst_valid = `InstValid;
				end
				`INST_SW:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = inst_i[20:16];
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadEnable;
					reg3_addr_o = 5'b00000; 
					reg3_write_o = `WriteDisable;
					alu_op_o =  `ALU_SW_OP;
					imm = `ZeroWord; 
					inst_valid = `InstValid;
				end
				`INST_SWL:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = inst_i[20:16];
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadEnable;
					reg3_addr_o = 5'b00000; 
					reg3_write_o = `WriteDisable;
					alu_op_o =  `ALU_SWL_OP;
					imm = `ZeroWord; 
					inst_valid = `InstValid;
				end
				`INST_SWR:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = inst_i[20:16];
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadEnable;
					reg3_addr_o = 5'b00000; 
					reg3_write_o = `WriteDisable;
					alu_op_o =  `ALU_SWR_OP;
					imm = `ZeroWord; 
					inst_valid = `InstValid;
				end
				
				`INST_SC:
				begin
					reg1_addr_o = inst_i[25:21];
					reg2_addr_o = inst_i[20:16];
					reg1_read_o = `ReadEnable; 
					reg2_read_o = `ReadEnable;
					reg3_addr_o = inst_i[20:16]; 
					reg3_write_o = `WriteEnable;
					alu_op_o =  `ALU_SC_OP;
					imm = `ZeroWord; 
					inst_valid = `InstValid;
				end
				6'b000000:
				begin
					case(inst_i[5:0])
						`INST_AND:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_AND_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_OR:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_OR_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_XOR:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_XOR_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_NOR:
						begin
						reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_NOR_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_SLLV:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_SLL_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_SRLV:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_SRL_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_SRAV:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_SRA_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_SYNC:
						begin
							reg1_addr_o = 5'b00000; 
							reg2_addr_o = 5'b00000; 
							reg1_read_o = `ReadDisable; 
							reg2_read_o = `ReadDisable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_NOP_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_SLL:
						begin
							reg1_addr_o = 5'b00000; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadDisable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_SLL_OP; 
							imm = inst_i[10:6]; 
							inst_valid = `InstValid;
						end
						`INST_SRL:
						begin
							reg1_addr_o = 5'b00000; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadDisable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_SRL_OP; 
							imm = inst_i[10:6]; 
							inst_valid = `InstValid;
						end
						`INST_SRA:
						begin
							reg1_addr_o = 5'b00000; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadDisable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_SRA_OP; 
							imm = inst_i[10:6]; 
							inst_valid = `InstValid;
						end			
						`INST_MOVN:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = (reg2_o == `ZeroWord)? `WriteDisable : `WriteEnable;
							alu_op_o =  `ALU_MOVN_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MOVZ:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16]; 
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = (reg2_o == `ZeroWord)? `WriteEnable : `WriteDisable;
							alu_op_o =  `ALU_MOVZ_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MFHI:
						begin
							reg1_addr_o = 5'b00000; 
							reg2_addr_o = 5'b00000;
							reg1_read_o = `ReadDisable;
							reg2_read_o = `ReadDisable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_MFHI_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MFLO:
						begin
							reg1_addr_o = 5'b00000; 
							reg2_addr_o = 5'b00000; 
							reg1_read_o = `ReadDisable;
							reg2_read_o = `ReadDisable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_MFLO_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MTHI:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = 5'b00000; 
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadDisable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_MTHI_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MTLO:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = 5'b00000; 
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadDisable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_MTLO_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_ADD:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16];
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_ADD_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_ADDU:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16];
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_ADDU_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_SUB:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16];
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_SUB_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_SUBU:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16];
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_SUBU_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_SLT:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16];
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_SLT_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_SLTU:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16];
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_SLTU_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MULT:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16];
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadEnable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_MULT_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MULTU:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16];
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadEnable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_MULTU_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						
						`INST_DIV:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16];
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadEnable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_DIV_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						
						`INST_DIVU:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = inst_i[20:16];
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadEnable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_DIVU_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						
						`INST_JR:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = 5'b00000;
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadDisable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_NOP_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
							
							jAddr_o = reg1_o;
							jCe_o = `JumpEnable;
							next_inst_is_in_delaySlot_o = `InDelaySlot;
						end
						`INST_JALR:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = 5'b00000;
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadDisable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_LINK_OP; 
							imm = `ZeroWord; 
							inst_valid = `InstValid;
							
							jAddr_o = reg1_o;
							link_addr_o = pc_add_8;
							jCe_o = `JumpEnable;
							next_inst_is_in_delaySlot_o = `InDelaySlot;
						end
						default:
						begin 
						end
					endcase
				end
				6'b011100:
				begin
					case(inst_i[5:0])
						`INST_CLZ:
						begin
							reg1_addr_o = inst_i[25:21];
							reg2_addr_o = 5'b00000;
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadDisable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_CLZ_OP;
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_CLO:
						begin
							reg1_addr_o = inst_i[25:21];
							reg2_addr_o = 5'b00000;
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadDisable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_CLO_OP;
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MUL:
						begin
							reg1_addr_o = inst_i[25:21];
							reg2_addr_o = inst_i[20:16];
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = inst_i[15:11]; 
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_MUL_OP;
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MADD:
						begin
							reg1_addr_o = inst_i[25:21];
							reg2_addr_o = inst_i[20:16];
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_MADD_OP;
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MADDU:
						begin
							reg1_addr_o = inst_i[25:21];
							reg2_addr_o = inst_i[20:16];
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_MADDU_OP;
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MSUB:
						begin
							reg1_addr_o = inst_i[25:21];
							reg2_addr_o = inst_i[20:16];
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_MSUB_OP;
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						`INST_MSUBU:
						begin
							reg1_addr_o = inst_i[25:21];
							reg2_addr_o = inst_i[20:16];
							reg1_read_o = `ReadEnable; 
							reg2_read_o = `ReadEnable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_MSUBU_OP;
							imm = `ZeroWord; 
							inst_valid = `InstValid;
						end
						default:
						begin
						end
					endcase
					
				end
				6'b000001:
				begin
					case(inst_i[20:16])
						`INST_BGEZ:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = 5'b00000; 
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadDisable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_NOP_OP; 
							imm = {{14{inst_i[15]}}, inst_i[15:0], 2'b00};
							inst_valid = `InstValid;
							if(reg1_o[31] != 1'b1)
							begin
								jAddr_o = pc_add_4 + imm;
								jCe_o = `JumpEnable;
								next_inst_is_in_delaySlot_o = `InDelaySlot;
							end	
						end
						`INST_BGEZAL:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = 5'b00000; 
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadDisable;
							reg3_addr_o = 5'b11111; 
							// reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_LINK_OP; 
							imm = {{14{inst_i[15]}}, inst_i[15:0], 2'b00};
							inst_valid = `InstValid;
							if(reg1_o[31] != 1'b1)
							begin
								jAddr_o = pc_add_4 + imm;
								jCe_o = `JumpEnable;
								next_inst_is_in_delaySlot_o = `InDelaySlot;
								reg3_write_o = `WriteEnable;
								link_addr_o = pc_add_8;
							end	
						end
						`INST_BLTZ:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = 5'b00000; 
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadDisable;
							reg3_addr_o = 5'b00000; 
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_NOP_OP; 
							imm = {{14{inst_i[15]}}, inst_i[15:0], 2'b00};
							inst_valid = `InstValid;
							if(reg1_o[31] == 1'b1)
							begin
								jAddr_o = pc_add_4 + imm;
								jCe_o = `JumpEnable;
								next_inst_is_in_delaySlot_o = `InDelaySlot;
							end	
						end
						`INST_BLTZAL:
						begin
							reg1_addr_o = inst_i[25:21]; 
							reg2_addr_o = 5'b00000; 
							reg1_read_o = `ReadEnable;
							reg2_read_o = `ReadDisable;
							reg3_addr_o = 5'b11111; 
							// reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_LINK_OP; 
							imm = {{14{inst_i[15]}}, inst_i[15:0], 2'b00};
							inst_valid = `InstValid;
							if(reg1_o[31] == 1'b1)
							begin
								jAddr_o = pc_add_4 + imm;
								jCe_o = `JumpEnable;
								next_inst_is_in_delaySlot_o = `InDelaySlot;
								reg3_write_o = `WriteEnable;
								link_addr_o = pc_add_8;
							end	
						end
						default:
						begin
						end
					endcase
				end
				`INST_COP0:
					case(inst_i[25:21])
						`MTC0:
						begin
							reg1_addr_o = 5'b00000; 
							reg2_addr_o = inst_i[20:16];
							reg1_read_o = `ReadDisable;
							reg2_read_o = `ReadEnable;
							reg3_addr_o = 5'b00000;
							reg3_write_o = `WriteDisable;
							alu_op_o =  `ALU_MTC0_OP; 
							imm = `ZeroWord;
							inst_valid = `InstValid;
						end
						`MFC0:
						begin
							reg1_addr_o = 5'b00000; 
							reg2_addr_o = 5'b00000;
							reg1_read_o = `ReadDisable; 
							reg2_read_o = `ReadDisable;
							reg3_addr_o = inst_i[20:16];
							reg3_write_o = `WriteEnable;
							alu_op_o =  `ALU_MFC0_OP; 
							imm = `ZeroWord;
							inst_valid = `InstValid;
						end
					endcase
				default:
				begin 
				end
			endcase
		end
			
		
	//为reg1_o赋值逻辑
	always@(*)
		if(rst == `RstEnable)
			reg1_o = `ZeroWord;		
		else if(reg1_read_o == `ReadDisable)
			reg1_o = imm;
			
		//从执行模块拿数据
		else if(reg1_read_o == `ReadEnable &&
				reg1_addr_o == ex_write_addr_i &&
				ex_write_ce_i == `WriteEnable)
			reg1_o = ex_write_data_i;
		//从访存模块拿数据
		else if(reg1_read_o == `ReadEnable &&
				reg1_addr_o == mem_write_addr_i &&
				mem_write_ce_i == `WriteEnable)
			reg1_o = mem_write_data_i;	
		
		else if(reg1_read_o == `ReadEnable)
			reg1_o = reg1_data_i;
		else
			reg1_o = `ZeroWord;
			
	//为reg2_o赋值逻辑
	always@(*)
		if(rst == `RstEnable)
			reg2_o = `ZeroWord;
		else if(reg2_read_o == `ReadDisable)
			reg2_o = imm;
		
		//从执行模块拿数据
		else if(reg2_read_o == `ReadEnable &&
				reg2_addr_o == ex_write_addr_i &&
				ex_write_ce_i == `WriteEnable)
			reg2_o = ex_write_data_i;
		//从访存模块拿数据
		else if(reg2_read_o == `ReadEnable &&
				reg2_addr_o == mem_write_addr_i &&
				mem_write_ce_i == `WriteEnable)
			reg2_o = mem_write_data_i;	
			
			
		else if(reg2_read_o == `ReadEnable)
			reg2_o = reg2_data_i;
		else
			reg2_o = `ZeroWord;
	
	
	//当前译码阶段的指令是否是延迟槽指令
	always@(*)
		if(rst == `RstEnable)
			is_in_delaySlot_o = `NotInDelaySlot;
		else
			is_in_delaySlot_o = is_in_delaySlot_i;
endmodule